/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "bsp.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
// 定义BNO055的I2C地址 (7位地址左移1位)

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
static TaskHandle_t xHandleTaskUartRx = NULL; // UART 接收处理任务句柄
static TaskHandle_t xHandleTaskUartShell = NULL;
SemaphoreHandle_t xUartRxSemaphore = NULL; // UART 接收数据可用的信号量（有数据时释放）
SemaphoreHandle_t xDmaMutex; // 用于保护 DMA 接收相关共享资源的互斥锁

SemaphoreHandle_t xUartMutex;					// 用于保护串口资源的互斥锁
SemaphoreHandle_t xTxSemaphore;				// 用于发送完成的信号量
QueueHandle_t xUartFrameQueue = NULL;	// 串口接收相关变量



/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
    .name = "defaultTask",
    .stack_size = 512,
    .priority = (osPriority_t) osPriorityNormal3,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
static void AppTaskUartRx(void *argument);  // UART 接收处理任务函数声明
static void AppTaskUartShell(void *argument);

/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void)
{
    /* USER CODE BEGIN Init */
    // 初始化串口DMA接收
    HAL_UART_Receive_DMA(&huart1, uart_rx_buffer, UART_RX_BUFFER_SIZE);
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);  // 使能空闲中断
    /* USER CODE END Init */
    /* USER CODE BEGIN RTOS_MUTEX */
    /* add mutexes, ... */
    xDmaMutex = xSemaphoreCreateMutex();
    xUartMutex = xSemaphoreCreateMutex();
    /* USER CODE END RTOS_MUTEX */
    /* USER CODE BEGIN RTOS_SEMAPHORES */
    /* add semaphores, ... */
    xTxSemaphore = xSemaphoreCreateBinary();
    xUartRxSemaphore = xSemaphoreCreateBinary();
    /* USER CODE END RTOS_SEMAPHORES */
    /* USER CODE BEGIN RTOS_TIMERS */
    /* start timers, add new ones, ... */
    /* USER CODE END RTOS_TIMERS */
    /* USER CODE BEGIN RTOS_QUEUES */
    /* add queues, ... */
    xUartFrameQueue = xQueueCreate(10, sizeof(UartFrame));
    /* USER CODE END RTOS_QUEUES */
    /* Create the thread(s) */
    /* creation of defaultTask */
    defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
    /* USER CODE BEGIN RTOS_THREADS */
    /* add threads, ... */
    xTaskCreate(AppTaskUartShell,
                "AppTaskUartShell",
                256,
                NULL,
                osPriorityNormal3,
                &xHandleTaskUartShell);
    xTaskCreate(AppTaskUartRx,	// 任务函数
                "AppTaskUartRx",	// 任务名称
                256, 				// 任务栈大小（512 字）
                NULL,		// 任务参数
                osPriorityNormal3,
                &xHandleTaskUartRx);
    /* USER CODE END RTOS_THREADS */
    /* USER CODE BEGIN RTOS_EVENTS */
    /* add events, ... */
    /* USER CODE END RTOS_EVENTS */
}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
    /* USER CODE BEGIN StartDefaultTask */
	HAL_Delay(3000);
	tBno055_Start(&hi2c1);
	tBno055_CheckCalibrationStatus(&hi2c1);
    /* Infinite loop */
    for (;;) {
//		bsp_LedToggle(1);
//		tBno055_CheckCalibrationStatus(&hi2c1);
		BNO055_ReadRawData(&hi2c1);
//		BNO055_ReadRawData(&hi2c1);
////		UART_SendData();
//		ValidateSensorData();
//		HAL_Delay(3000);
        osDelay(1);
    }

    /* USER CODE END StartDefaultTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
static void AppTaskUartShell(void *argument)
{
    UartFrame frame;

    /* 初始化任务 */
    while (1) {
        if (xQueueReceive(xUartFrameQueue, &frame, 0) == pdTRUE) {
            ProcessUartFrame(&frame);
        }

        vTaskDelay(10);
    }
}

static void AppTaskUartRx(void *argument)
{
    uint16_t data_length;
    uint32_t last_pos, current_pos;
    bsp_LedOff(1);

    while (1) {
        if (xSemaphoreTake(xUartRxSemaphore, portMAX_DELAY) == pdTRUE) {
            // 使用信号量或互斥锁保护共享资源
            if (xSemaphoreTake(xDmaMutex, pdMS_TO_TICKS(10)) == pdTRUE) {
                last_pos = dma_last_pos;
                current_pos = dma_current_pos;
                xSemaphoreGive(xDmaMutex);

                if (current_pos >= last_pos) {
                    data_length = current_pos - last_pos;
                } else {
                    data_length = UART_RX_BUFFER_SIZE - last_pos + current_pos;
                }

                if (data_length > 0) {
                    ProcessUartData(last_pos, data_length);

                    if (xSemaphoreTake(xDmaMutex, pdMS_TO_TICKS(10)) == pdTRUE) {
                        dma_last_pos = current_pos;
                        xSemaphoreGive(xDmaMutex);
                    }
                }
            }
        }

        vTaskDelay(1);
    }
}



/* USER CODE END Application */

